package main

import (
	"fmt"
	"log"
	"os"

	"github.com/kataras/iris/v12"

	// "github.com/kataras/iris/v12/mvc"
	"database/sql"

	_ "github.com/go-sql-driver/mysql"
	"github.com/kataras/golog"
	"github.com/kataras/iris/v12/middleware/accesslog"
	"github.com/kataras/pio"
)

// Read the example and its comments carefully.
func makeAccessLog() *accesslog.AccessLog {
	// Initialize a new access log middleware.
	ac := accesslog.File("./access.log")
	// Remove this line to disable logging to console:
	ac.AddOutput(os.Stdout)

	// The default configuration:
	ac.Delim = '|'
	ac.TimeFormat = "2006-01-02 15:04:05"
	ac.Async = false
	ac.IP = true
	ac.BytesReceivedBody = true
	ac.BytesSentBody = true
	ac.BytesReceived = false
	ac.BytesSent = false
	ac.BodyMinify = true
	ac.RequestBody = true
	ac.ResponseBody = false
	ac.KeepMultiLineError = true
	ac.PanicLog = accesslog.LogHandler

	// Default line format if formatter is missing:
	// Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response|
	//
	// Set Custom Formatter:
	ac.SetFormatter(&accesslog.JSON{
		Indent:    "  ",
		HumanTime: true,
	})
	// ac.SetFormatter(&accesslog.CSV{})
	// ac.SetFormatter(&accesslog.Template{Text: "{{.Code}}"})

	return ac
}

func main() {

	ac := makeAccessLog()
	defer ac.Close() // Close the underline file.

	app := iris.New()
	// Register the middleware (UseRouter to catch http errors too).
	app.UseRouter(ac.Handler)

	level := golog.Levels[golog.DebugLevel]
	level.Name = "debug"         // default
	level.Title = "[DBUG]"       // default
	level.ColorCode = pio.Yellow // default
	// app.Logger().SetFormat("json", "    ")
	app.Logger().SetLevelOutput("info", os.Stderr)

	booksAPI := app.Party("/books")
	{
		booksAPI.Use(iris.Compression)

		// GET: http://localhost:8080/books
		booksAPI.Get("/", list)
		// POST: http://localhost:8080/books
		booksAPI.Post("/", create)
	}

	// m := mvc.New(booksAPI)
	// m.Handle(new(BookController))

	app.Listen(":8080")
}

// type BookController struct {
//     /* dependencies */
// }

// // GET: http://localhost:8080/books
// func (c *BookController) Get() []Book {
//     return []Book{
//         {"Mastering Concurrency in Go"},
//         {"Go Design Patterns"},
//         {"Black Hat Go"},
//     }
// }

// // POST: http://localhost:8080/books
// func (c *BookController) Post(b Book) int {
//     println("Received Book: " + b.Title)

//     return iris.StatusCreated
// }

// Book example.
type Book struct {
	// Id int `json:"id"`
	Title string `json:"title"`
}

func list(ctx iris.Context) {
	books := []Book{
		{"Mastering Concurrency in Go"},
		{"Go Design Patterns"},
		{"Black Hat Go"},
	}
	// books := queryItem()
	ctx.JSON(books)
	// TIP: negotiate the response between server's prioritizes
	// and client's requirements, instead of ctx.JSON:
	// ctx.Negotiation().JSON().MsgPack().Protobuf()
	// ctx.Negotiate(books)
}

func create(ctx iris.Context) {
	var b Book
	err := ctx.ReadJSON(&b)
	// TIP: use ctx.ReadBody(&b) to bind
	// any type of incoming data instead.
	if err != nil {
		ctx.StopWithProblem(iris.StatusBadRequest, iris.NewProblem().
			Title("Book creation failure").DetailErr(err))
		// TIP: use ctx.StopWithError(code, err) when only
		// plain text responses are expected on errors.
		return
	}

	println("Received Book: " + b.Title)

	ctx.StatusCode(iris.StatusCreated)
}

// DB Mysql
func showMysqlVersion() {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(192.168.6.63:3306)/test?charset=utf8mb4")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("数据库连接失败！")
		log.Fatalln(err)
	}

	var version string

	err2 := db.QueryRow("SELECT VERSION()").Scan(&version)

	if err2 != nil {
		log.Fatal(err2)
	}

	fmt.Println(version)
}
func createTable() {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(127.0.0.1:3306)/TestDB")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("connect DB error !")
		log.Fatalln(err)
	}

	_, err2 := db.Exec("CREATE TABLE user(id INT NOT NULL , name VARCHAR(20), PRIMARY KEY(ID));")
	if err2 != nil {
		log.Fatal(err2)
	}

	fmt.Println("successfully create table")
}

func insertItem() {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(127.0.0.1:3306)/TestDB?charset=utf8mb4")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("connect DB error !")
		log.Fatalln(err)
	}

	_, err2 := db.Query("INSERT INTO book VALUES(4, 'xxxxxxx')")
	if err2 != nil {
		log.Fatal(err2)
	}

	fmt.Println("successfully insert item")
}

func deleteItem() {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(127.0.0.1:3306)/TestDB?charset=utf8mb4")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("connect DB error !")
		log.Fatalln(err)
	}

	sql := "DELETE FROM user WHERE id = 1"
	res, err2 := db.Exec(sql)

	if err2 != nil {
		panic(err2.Error())
	}

	affectedRows, err := res.RowsAffected()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("delete item success, statement affected %d rows\n", affectedRows)
}

func alterItem() {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(127.0.0.1:3306)/TestDB?charset=utf8mb4")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("connect DB error !")
		log.Fatalln(err)
	}

	sql := "update user set name = ? WHERE id = ?"
	res, err2 := db.Exec(sql, "lisi", 1)

	if err2 != nil {
		panic(err2.Error())
	}

	affectedRows, err := res.RowsAffected()

	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("alter item success, statement affected %d rows\n", affectedRows)
}

func queryItem() []Book {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(192.168.6.63:3306)/test?charset=utf8mb4")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("connect DB error !")
		log.Fatalln(err)
	}

	// var mid int = 1

	result, err2 := db.Query("SELECT * FROM book limit 10")
	if err2 != nil {
		log.Fatal(err2)
	}

	books := []Book{}
	for result.Next() {

		var id int
		var title string

		err = result.Scan(&id, &title)

		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("id: %d, name: %s\n", id, title)
		var b Book
		b.Title = title
		books = append(books, b)
	}
	return books
}

func dropTable() {
	db, err := sql.Open("mysql", "root:algebrafly@tcp(127.0.0.1:3306)/TestDB")
	db.Ping()
	defer db.Close()

	if err != nil {
		fmt.Println("connect DB error !")
		log.Fatalln(err)
	}

	_, err2 := db.Exec("DROP TABLE user;")
	if err2 != nil {
		log.Fatal(err2)
	}

	fmt.Println("successfully drop table")
}
